#include <string>
#include <map>
#include "executor.h"
#include "net.h"

#ifndef _BROKER_H
#define _BROKER_H

#define ALREADY_CONNECTED_ERR -1

using std::string;
using std::map;
using net::Socket;

class Broker {
    public:
        // logic
        Broker(string id, Socket* socket);
	bool connect(Socket* socket);
	void disconnect();
        // model
	string id();
    private:
	string broker_id;
	Socket* socket;
};

class ContextConfig {
    public:
        virtual int poolSize() = 0;
};

class DefaultContextConfig : public ContextConfig {
    public:
        int poolSize() { return 10; }
};

class Context {
    public:
        Context(ContextConfig* config = new DefaultContextConfig());
        void enqueue(Job* job);
	bool put(Broker* broker);
	Broker* broker(string client_id);
	Broker* remove(string client_id);
    private:
        ContextConfig* config;
	Executor* executor;
	map<string, Broker*> brokers;
};

class InitServerJob : public Job {
    public:
        InitServerJob(Socket* socket, Context* ctx);
	Job* execute();
    private:
        Socket* socket;
        Broker* broker;
	Context* ctx;
};

class LinkJob : public Job {
    public:
        LinkJob(Broker* broker, Socket* client_socket, Context* ctx);
	Job* execute();
    private:
        Socket* client_socket;
	Broker* broker;
	Context* ctx;
};

// 
// Util fuctions
//
string readId(Socket* socket);
void closeConnectionWithError(Socket* socket, int error);

#endif

